/**   
* @Title: ActionBarSherlock.java 
* @Package com.actionbarsherlock 
* @Description: 
*			声明:
*			1)掌控校园是本人的大学的创业作品,也是本人的毕业设计
*			2)本程序尚未进行开放源代码,所以禁止组织或者是个人泄露源码,否则将会追究其刑事责任
*			3)编写本软件,我需要感谢彭老师以及其他鼓励和支持我的同学以及朋友
*			4)本程序的最终所有权属于本人	
* @author  张雷 794857063@qq.com
* @date 2013-11-14 19:33:57 
* @version V1.0   
*/
package com.actionbarsherlock;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.internal.ActionBarSherlockCompat;
import com.actionbarsherlock.internal.ActionBarSherlockNative;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;

// TODO: Auto-generated Javadoc
/**
 * <p>
 * Helper for implementing the action bar design pattern across all versions of
 * Android.
 * </p>
 * 
 * <p>
 * This class will manage interaction with a custom action bar based on the
 * Android 4.0 source code. The exposed API mirrors that of its native
 * counterpart and you should refer to its documentation for instruction.
 * </p>
 * 
 * @author Jake Wharton <jakewharton@gmail.com>
 */
public abstract class ActionBarSherlock {
	
	/** The Constant TAG. */
	protected static final String TAG = "ActionBarSherlock";
	
	/** The Constant DEBUG. */
	protected static final boolean DEBUG = false;

	/** The Constant CONSTRUCTOR_ARGS. */
	private static final Class<?>[] CONSTRUCTOR_ARGS = new Class[] {
			Activity.class, int.class };
	
	/** The Constant IMPLEMENTATIONS. */
	private static final HashMap<Implementation, Class<? extends ActionBarSherlock>> IMPLEMENTATIONS = new HashMap<Implementation, Class<? extends ActionBarSherlock>>();

	static {
		// Register our two built-in implementations
		registerImplementation(ActionBarSherlockCompat.class);
		registerImplementation(ActionBarSherlockNative.class);
	}

	/**
	 * <p>
	 * Denotes an implementation of ActionBarSherlock which provides an action
	 * bar-enhanced experience.
	 * </p>
	 */
	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	public @interface Implementation {
		
		/** The Constant DEFAULT_API. */
		static final int DEFAULT_API = -1;
		
		/** The Constant DEFAULT_DPI. */
		static final int DEFAULT_DPI = -1;

		/**
		 * Api.
		 * 
		 * @return the int
		 */
		int api() default DEFAULT_API;

		/**
		 * Dpi.
		 * 
		 * @return the int
		 */
		int dpi() default DEFAULT_DPI;
	}

	/**
	 * Activity interface for menu creation callback.
	 * 
	 * @see OnCreatePanelMenuEvent
	 */
	public interface OnCreatePanelMenuListener {
		
		/**
		 * On create panel menu.
		 * 
		 * @param featureId
		 *            the feature id
		 * @param menu
		 *            the menu
		 * @return true, if successful
		 */
		public boolean onCreatePanelMenu(int featureId, Menu menu);
	}

	/**
	 * Activity interface for menu creation callback.
	 * 
	 * @see OnCreateOptionsMenuEvent
	 */
	public interface OnCreateOptionsMenuListener {
		
		/**
		 * On create options menu.
		 * 
		 * @param menu
		 *            the menu
		 * @return true, if successful
		 */
		public boolean onCreateOptionsMenu(Menu menu);
	}

	/**
	 * Activity interface for menu item selection callback.
	 * 
	 * @see OnMenuItemSelectedEvent
	 */
	public interface OnMenuItemSelectedListener {
		
		/**
		 * On menu item selected.
		 * 
		 * @param featureId
		 *            the feature id
		 * @param item
		 *            the item
		 * @return true, if successful
		 */
		public boolean onMenuItemSelected(int featureId, MenuItem item);
	}

	/**
	 * Activity interface for menu item selection callback.
	 * 
	 * @see OnOptionsItemSelectedEvent
	 */
	public interface OnOptionsItemSelectedListener {
		
		/**
		 * On options item selected.
		 * 
		 * @param item
		 *            the item
		 * @return true, if successful
		 */
		public boolean onOptionsItemSelected(MenuItem item);
	}

	/**
	 * Activity interface for menu preparation callback.
	 * 
	 * @see OnPreparePanelEvent
	 */
	public interface OnPreparePanelListener {
		
		/**
		 * On prepare panel.
		 * 
		 * @param featureId
		 *            the feature id
		 * @param view
		 *            the view
		 * @param menu
		 *            the menu
		 * @return true, if successful
		 */
		public boolean onPreparePanel(int featureId, View view, Menu menu);
	}

	/**
	 * Activity interface for menu preparation callback.
	 * 
	 * @see OnPrepareOptionsMenuEvent
	 */
	public interface OnPrepareOptionsMenuListener {
		
		/**
		 * On prepare options menu.
		 * 
		 * @param menu
		 *            the menu
		 * @return true, if successful
		 */
		public boolean onPrepareOptionsMenu(Menu menu);
	}

	/**
	 * Activity interface for action mode finished callback.
	 * 
	 * @see OnActionModeFinishedEvent
	 */
	public interface OnActionModeFinishedListener {
		
		/**
		 * On action mode finished.
		 * 
		 * @param mode
		 *            the mode
		 */
		public void onActionModeFinished(ActionMode mode);
	}

	/**
	 * Activity interface for action mode started callback.
	 * 
	 * @see OnActionModeStartedEvent
	 */
	public interface OnActionModeStartedListener {
		
		/**
		 * On action mode started.
		 * 
		 * @param mode
		 *            the mode
		 */
		public void onActionModeStarted(ActionMode mode);
	}

	/**
	 * If set, the logic in these classes will assume that an {@link Activity}
	 * is dispatching all of the required events to the class. This flag should
	 * only be used internally or if you are creating your own base activity
	 * modeled after one of the included types (e.g., {@code SherlockActivity}).
	 */
	public static final int FLAG_DELEGATE = 1;

	/**
	 * Register an ActionBarSherlock implementation.
	 * 
	 * @param implementationClass
	 *            Target implementation class which extends
	 *            {@link ActionBarSherlock}. This class must also be annotated
	 *            with {@link Implementation}.
	 */
	public static void registerImplementation(
			Class<? extends ActionBarSherlock> implementationClass) {
		if (!implementationClass.isAnnotationPresent(Implementation.class)) {
			throw new IllegalArgumentException("Class "
					+ implementationClass.getSimpleName()
					+ " is not annotated with @Implementation");
		} else if (IMPLEMENTATIONS.containsValue(implementationClass)) {
			if (DEBUG)
				Log.w(TAG, "Class " + implementationClass.getSimpleName()
						+ " already registered");
			return;
		}

		Implementation impl = implementationClass
				.getAnnotation(Implementation.class);
		if (DEBUG)
			Log.i(TAG, "Registering " + implementationClass.getSimpleName()
					+ " with qualifier " + impl);
		IMPLEMENTATIONS.put(impl, implementationClass);
	}

	/**
	 * Unregister an ActionBarSherlock implementation. <strong>This should be
	 * considered very volatile and you should only use it if you know what you
	 * are doing.</strong> You have been warned.
	 * 
	 * @param implementationClass
	 *            Target implementation class.
	 * @return Boolean indicating whether the class was removed.
	 */
	public static boolean unregisterImplementation(
			Class<? extends ActionBarSherlock> implementationClass) {
		return IMPLEMENTATIONS.values().remove(implementationClass);
	}

	/**
	 * Wrap an activity with an action bar abstraction which will enable the use
	 * of a custom implementation on platforms where a native version does not
	 * exist.
	 * 
	 * @param activity
	 *            Activity to wrap.
	 * @return Instance to interact with the action bar.
	 */
	public static ActionBarSherlock wrap(Activity activity) {
		return wrap(activity, 0);
	}

	/**
	 * Wrap an activity with an action bar abstraction which will enable the use
	 * of a custom implementation on platforms where a native version does not
	 * exist.
	 * 
	 * @param activity
	 *            Owning activity.
	 * @param flags
	 *            Option flags to control behavior.
	 * @return Instance to interact with the action bar.
	 */
	public static ActionBarSherlock wrap(Activity activity, int flags) {
		// Create a local implementation map we can modify
		HashMap<Implementation, Class<? extends ActionBarSherlock>> impls = new HashMap<Implementation, Class<? extends ActionBarSherlock>>(
				IMPLEMENTATIONS);
		boolean hasQualfier;

		/* DPI FILTERING */
		hasQualfier = false;
		for (Implementation key : impls.keySet()) {
			// Only honor TVDPI as a specific qualifier
			if (key.dpi() == DisplayMetrics.DENSITY_TV) {
				hasQualfier = true;
				break;
			}
		}
		if (hasQualfier) {
			final boolean isTvDpi = activity.getResources().getDisplayMetrics().densityDpi == DisplayMetrics.DENSITY_TV;
			for (Iterator<Implementation> keys = impls.keySet().iterator(); keys
					.hasNext();) {
				int keyDpi = keys.next().dpi();
				if ((isTvDpi && keyDpi != DisplayMetrics.DENSITY_TV)
						|| (!isTvDpi && keyDpi == DisplayMetrics.DENSITY_TV)) {
					keys.remove();
				}
			}
		}

		/* API FILTERING */
		hasQualfier = false;
		for (Implementation key : impls.keySet()) {
			if (key.api() != Implementation.DEFAULT_API) {
				hasQualfier = true;
				break;
			}
		}
		if (hasQualfier) {
			final int runtimeApi = Build.VERSION.SDK_INT;
			int bestApi = 0;
			for (Iterator<Implementation> keys = impls.keySet().iterator(); keys
					.hasNext();) {
				int keyApi = keys.next().api();
				if (keyApi > runtimeApi) {
					keys.remove();
				} else if (keyApi > bestApi) {
					bestApi = keyApi;
				}
			}
			for (Iterator<Implementation> keys = impls.keySet().iterator(); keys
					.hasNext();) {
				if (keys.next().api() != bestApi) {
					keys.remove();
				}
			}
		}

		if (impls.size() > 1) {
			throw new IllegalStateException(
					"More than one implementation matches configuration.");
		}
		if (impls.isEmpty()) {
			throw new IllegalStateException(
					"No implementations match configuration.");
		}
		Class<? extends ActionBarSherlock> impl = impls.values().iterator()
				.next();
		if (DEBUG)
			Log.i(TAG, "Using implementation: " + impl.getSimpleName());

		try {
			Constructor<? extends ActionBarSherlock> ctor = impl
					.getConstructor(CONSTRUCTOR_ARGS);
			return ctor.newInstance(activity, flags);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			// return null;
			throw new RuntimeException(e);
		} catch (IllegalArgumentException e) {
			throw new RuntimeException(e);
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e);
		}
	}

	/** Activity which is displaying the action bar. Also used for context. */
	protected final Activity mActivity;
	/** Whether delegating actions for the activity or managing ourselves. */
	protected final boolean mIsDelegate;

	/** Reference to our custom menu inflater which supports action items. */
	protected MenuInflater mMenuInflater;

	/**
	 * Instantiates a new action bar sherlock.
	 * 
	 * @param activity
	 *            the activity
	 * @param flags
	 *            the flags
	 */
	protected ActionBarSherlock(Activity activity, int flags) {
		if (DEBUG)
			Log.d(TAG, "[<ctor>] activity: " + activity + ", flags: " + flags);

		mActivity = activity;
		mIsDelegate = (flags & FLAG_DELEGATE) != 0;
	}

	/**
	 * Get the current action bar instance.
	 * 
	 * @return Action bar instance.
	 */
	public abstract ActionBar getActionBar();

	// /////////////////////////////////////////////////////////////////////////
	// Lifecycle and interaction callbacks when delegating
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Notify action bar of a configuration change event. Should be dispatched
	 * after the call to the superclass implementation.
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * &#064;Override
	 * public void onConfigurationChanged(Configuration newConfig) {
	 * 	super.onConfigurationChanged(newConfig);
	 * 	mSherlock.dispatchConfigurationChanged(newConfig);
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param newConfig
	 *            The new device configuration.
	 */
	public void dispatchConfigurationChanged(Configuration newConfig) {
	}

	/**
	 * Notify the action bar that the activity has finished its resuming. This
	 * should be dispatched after the call to the superclass implementation.
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * &#064;Override
	 * protected void onPostResume() {
	 * 	super.onPostResume();
	 * 	mSherlock.dispatchPostResume();
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 */
	public void dispatchPostResume() {
	}

	/**
	 * Notify the action bar that the activity is pausing. This should be
	 * dispatched before the call to the superclass implementation.
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * &#064;Override
	 * protected void onPause() {
	 * 	mSherlock.dispatchPause();
	 * 	super.onPause();
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 */
	public void dispatchPause() {
	}

	/**
	 * Notify the action bar that the activity is stopping. This should be
	 * called before the superclass implementation.
	 * 
	 * <blockquote>
	 * <p>
	 * 
	 * @Override protected void onStop() { mSherlock.dispatchStop();
	 *           super.onStop(); }
	 *           </p>
	 *           </blockquote>
	 */
	public void dispatchStop() {
	}

	/**
	 * Indicate that the menu should be recreated by calling.
	 * 
	 * {@link OnCreateOptionsMenuListener#onCreateOptionsMenu(com.actionbarsherlock.view.Menu)}
	 * .
	 */
	public abstract void dispatchInvalidateOptionsMenu();

	/**
	 * Notify the action bar that it should display its overflow menu if it is
	 * appropriate for the device. The implementation should conditionally call
	 * the superclass method only if this method returns {@code false}.
	 * 
	 * <blockquote>
	 * <p>
	 * 
	 * @return {@code true} if the opening of the menu was handled internally.
	 * @Override public void openOptionsMenu() { if
	 *           (!mSherlock.dispatchOpenOptionsMenu()) {
	 *           super.openOptionsMenu(); } }
	 *           </p>
	 *           </blockquote>
	 */
	public boolean dispatchOpenOptionsMenu() {
		return false;
	}

	/**
	 * Notify the action bar that it should close its overflow menu if it is
	 * appropriate for the device. This implementation should conditionally call
	 * the superclass method only if this method returns {@code false}.
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * &#064;Override
	 * public void closeOptionsMenu() {
	 * 	if (!mSherlock.dispatchCloseOptionsMenu()) {
	 * 		super.closeOptionsMenu();
	 * 	}
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @return {@code true} if the closing of the menu was handled internally.
	 */
	public boolean dispatchCloseOptionsMenu() {
		return false;
	}

	/**
	 * Notify the class that the activity has finished its creation. This should
	 * be called after the superclass implementation.
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * &#064;Override
	 * protected void onPostCreate(Bundle savedInstanceState) {
	 * 	mSherlock.dispatchPostCreate(savedInstanceState);
	 * 	super.onPostCreate(savedInstanceState);
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param savedInstanceState
	 *            If the activity is being re-initialized after previously being
	 *            shut down then this Bundle contains the data it most recently
	 *            supplied in {@link Activity#}onSaveInstanceState(Bundle)}.
	 *            <strong>Note: Otherwise it is null.</strong>
	 */
	public void dispatchPostCreate(Bundle savedInstanceState) {
	}

	/**
	 * Notify the action bar that the title has changed and the action bar
	 * should be updated to reflect the change. This should be called before the
	 * superclass implementation.
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * &#064;Override
	 * protected void onTitleChanged(CharSequence title, int color) {
	 * 	mSherlock.dispatchTitleChanged(title, color);
	 * 	super.onTitleChanged(title, color);
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param title
	 *            New activity title.
	 * @param color
	 *            New activity color.
	 */
	public void dispatchTitleChanged(CharSequence title, int color) {
	}

	/**
	 * Notify the action bar the user has created a key event. This is used to
	 * toggle the display of the overflow action item with the menu key and to
	 * close the action mode or expanded action item with the back key.
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * &#064;Override
	 * public boolean dispatchKeyEvent(KeyEvent event) {
	 * 	if (mSherlock.dispatchKeyEvent(event)) {
	 * 		return true;
	 * 	}
	 * 	return super.dispatchKeyEvent(event);
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param event
	 *            Description of the key event.
	 * @return {@code true} if the event was handled.
	 */
	public boolean dispatchKeyEvent(KeyEvent event) {
		return false;
	}

	/**
	 * Notify the action bar that the Activity has triggered a menu creation
	 * which should happen on the conclusion of {@link Activity#onCreate}. This
	 * will be used to gain a reference to the native menu for native and
	 * overflow binding as well as to indicate when compatibility create should
	 * occur for the first time.
	 * 
	 * @param menu
	 *            Activity native menu.
	 * @return {@code true} since we always want to say that we have a native
	 */
	public abstract boolean dispatchCreateOptionsMenu(android.view.Menu menu);

	/**
	 * Notify the action bar that the Activity has triggered a menu preparation
	 * which usually means that the user has requested the overflow menu via a
	 * hardware menu key. You should return the result of this method call and
	 * not call the superclass implementation.
	 * 
	 * <blockquote>
	 * <p>
	 * 
	 * @param menu
	 *            Activity native menu.
	 * @return {@code true} if menu display should proceed.
	 * @Override public final boolean onPrepareOptionsMenu(android.view.Menu
	 *           menu) { return mSherlock.dispatchPrepareOptionsMenu(menu); }
	 *           </p>
	 *           </blockquote>
	 */
	public abstract boolean dispatchPrepareOptionsMenu(android.view.Menu menu);

	/**
	 * Notify the action bar that a native options menu item has been selected.
	 * The implementation should return the result of this method call.
	 * 
	 * <blockquote>
	 * <p>
	 * 
	 * @param item
	 *            Options menu item.
	 * @return @{code true} if the selection was handled.
	 * @Override public final boolean
	 *           onOptionsItemSelected(android.view.MenuItem item) { return
	 *           mSherlock.dispatchOptionsItemSelected(item); }
	 *           </p>
	 *           </blockquote>
	 */
	public abstract boolean dispatchOptionsItemSelected(
			android.view.MenuItem item);

	/**
	 * Notify the action bar that the overflow menu has been opened. The
	 * implementation should conditionally return {@code true} if this method
	 * returns {@code true}, otherwise return the result of the superclass
	 * method.
	 * 
	 * <blockquote>
	 * <p>
	 * 
	 * @param featureId
	 *            Window feature which triggered the event.
	 * @param menu
	 *            Activity native menu.
	 * @return {@code true} if the event was handled by this method.
	 * @Override public final boolean onMenuOpened(int featureId,
	 *           android.view.Menu menu) { if
	 *           (mSherlock.dispatchMenuOpened(featureId, menu)) { return true;
	 *           } return super.onMenuOpened(featureId, menu); }
	 *           </p>
	 *           </blockquote>
	 */
	public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) {
		return false;
	}

	/**
	 * Notify the action bar that the overflow menu has been closed. This method
	 * should be called before the superclass implementation.
	 * 
	 * <blockquote>
	 * <p>
	 * 
	 * @param featureId
	 *            the feature id
	 * @param menu
	 *            the menu
	 * @Override public void onPanelClosed(int featureId, android.view.Menu
	 *           menu) { mSherlock.dispatchPanelClosed(featureId, menu);
	 *           super.onPanelClosed(featureId, menu); }
	 *           </p>
	 *           </blockquote>
	 */
	public void dispatchPanelClosed(int featureId, android.view.Menu menu) {
	}

	/**
	 * Notify the action bar that the activity has been destroyed. This method
	 * should be called before the superclass implementation.
	 * 
	 * <blockquote>
	 * <p>
	 * 
	 * @Override public void onDestroy() { mSherlock.dispatchDestroy();
	 *           super.onDestroy(); }
	 *           </p>
	 *           </blockquote>
	 */
	public void dispatchDestroy() {
	}

	/**
	 * Dispatch save instance state.
	 * 
	 * @param outState
	 *            the out state
	 */
	public void dispatchSaveInstanceState(Bundle outState) {
	}

	/**
	 * Dispatch restore instance state.
	 * 
	 * @param savedInstanceState
	 *            the saved instance state
	 */
	public void dispatchRestoreInstanceState(Bundle savedInstanceState) {
	}

	// /////////////////////////////////////////////////////////////////////////
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Internal method to trigger the menu creation process.
	 * 
	 * @param menu
	 *            the menu
	 * @return {@code true} if menu creation should proceed.
	 */
	protected final boolean callbackCreateOptionsMenu(Menu menu) {
		if (DEBUG)
			Log.d(TAG, "[callbackCreateOptionsMenu] menu: " + menu);

		boolean result = true;
		if (mActivity instanceof OnCreatePanelMenuListener) {
			OnCreatePanelMenuListener listener = (OnCreatePanelMenuListener) mActivity;
			result = listener.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL,
					menu);
		} else if (mActivity instanceof OnCreateOptionsMenuListener) {
			OnCreateOptionsMenuListener listener = (OnCreateOptionsMenuListener) mActivity;
			result = listener.onCreateOptionsMenu(menu);
		}

		if (DEBUG)
			Log.d(TAG, "[callbackCreateOptionsMenu] returning " + result);
		return result;
	}

	/**
	 * Internal method to trigger the menu preparation process.
	 * 
	 * @param menu
	 *            the menu
	 * @return {@code true} if menu preparation should proceed.
	 */
	protected final boolean callbackPrepareOptionsMenu(Menu menu) {
		if (DEBUG)
			Log.d(TAG, "[callbackPrepareOptionsMenu] menu: " + menu);

		boolean result = true;
		if (mActivity instanceof OnPreparePanelListener) {
			OnPreparePanelListener listener = (OnPreparePanelListener) mActivity;
			result = listener.onPreparePanel(Window.FEATURE_OPTIONS_PANEL,
					null, menu);
		} else if (mActivity instanceof OnPrepareOptionsMenuListener) {
			OnPrepareOptionsMenuListener listener = (OnPrepareOptionsMenuListener) mActivity;
			result = listener.onPrepareOptionsMenu(menu);
		}

		if (DEBUG)
			Log.d(TAG, "[callbackPrepareOptionsMenu] returning " + result);
		return result;
	}

	/**
	 * Internal method for dispatching options menu selection to the owning
	 * activity callback.
	 * 
	 * @param item
	 *            Selected options menu item.
	 * @return {@code true} if the item selection was handled in the callback.
	 */
	protected final boolean callbackOptionsItemSelected(MenuItem item) {
		if (DEBUG)
			Log.d(TAG,
					"[callbackOptionsItemSelected] item: "
							+ item.getTitleCondensed());

		boolean result = false;
		if (mActivity instanceof OnMenuItemSelectedListener) {
			OnMenuItemSelectedListener listener = (OnMenuItemSelectedListener) mActivity;
			result = listener.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL,
					item);
		} else if (mActivity instanceof OnOptionsItemSelectedListener) {
			OnOptionsItemSelectedListener listener = (OnOptionsItemSelectedListener) mActivity;
			result = listener.onOptionsItemSelected(item);
		}

		if (DEBUG)
			Log.d(TAG, "[callbackOptionsItemSelected] returning " + result);
		return result;
	}

	// /////////////////////////////////////////////////////////////////////////
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Query for the availability of a certain feature.
	 * 
	 * @param featureId
	 *            The feature ID to check.
	 * @return {@code true} if feature is enabled, {@code false} otherwise.
	 */
	public abstract boolean hasFeature(int featureId);

	/**
	 * Enable extended screen features. This must be called before
	 * 
	 * @param featureId
	 *            The desired features, defined as constants by Window.
	 * @return Returns true if the requested feature is supported and now
	 *         enabled. {@code setContentView()}. May be called as many times as
	 *         desired as long as it is before {@code setContentView()}. If not
	 *         called, no extended features will be available. You can not turn
	 *         off a feature once it is requested.
	 */
	public abstract boolean requestFeature(int featureId);

	/**
	 * Set extra options that will influence the UI for this window.
	 * 
	 * @param uiOptions
	 *            Flags specifying extra options for this window.
	 */
	public abstract void setUiOptions(int uiOptions);

	/**
	 * Set extra options that will influence the UI for this window. Only the
	 * bits filtered by mask will be modified.
	 * 
	 * @param uiOptions
	 *            Flags specifying extra options for this window.
	 * @param mask
	 *            Flags specifying which options should be modified. Others will
	 *            remain unchanged.
	 */
	public abstract void setUiOptions(int uiOptions, int mask);

	/**
	 * Set the content of the activity inside the action bar.
	 * 
	 * @param layoutResId
	 *            Layout resource ID.
	 */
	public abstract void setContentView(int layoutResId);

	/**
	 * Set the content of the activity inside the action bar.
	 * 
	 * @param view
	 *            The desired content to display.
	 */
	public void setContentView(View view) {
		if (DEBUG)
			Log.d(TAG, "[setContentView] view: " + view);

		setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT,
				MATCH_PARENT));
	}

	/**
	 * Set the content of the activity inside the action bar.
	 * 
	 * @param view
	 *            The desired content to display.
	 * @param params
	 *            Layout parameters to apply to the view.
	 */
	public abstract void setContentView(View view, ViewGroup.LayoutParams params);

	/**
	 * Variation on.
	 * 
	 * @param view
	 *            The desired content to display.
	 * @param params
	 *            Layout parameters for the view.
	 *            {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}
	 *            to add an additional content view to the screen. Added after
	 *            any existing ones on the screen -- existing views are NOT
	 *            removed.
	 */
	public abstract void addContentView(View view, ViewGroup.LayoutParams params);

	/**
	 * Change the title associated with this activity.
	 * 
	 * @param title
	 *            the new title
	 */
	public abstract void setTitle(CharSequence title);

	/**
	 * Change the title associated with this activity.
	 * 
	 * @param resId
	 *            the new title
	 */
	public void setTitle(int resId) {
		if (DEBUG)
			Log.d(TAG, "[setTitle] resId: " + resId);

		setTitle(mActivity.getString(resId));
	}

	/**
	 * Sets the visibility of the progress bar in the title.
	 * <p>
	 * In order for the progress bar to be shown, the feature must be requested
	 * via {@link #requestWindowFeature(int)}.
	 * 
	 * @param visible
	 *            Whether to show the progress bars in the title.
	 */
	public abstract void setProgressBarVisibility(boolean visible);

	/**
	 * Sets the visibility of the indeterminate progress bar in the title.
	 * <p>
	 * In order for the progress bar to be shown, the feature must be requested
	 * via {@link #requestWindowFeature(int)}.
	 * 
	 * @param visible
	 *            Whether to show the progress bars in the title.
	 */
	public abstract void setProgressBarIndeterminateVisibility(boolean visible);

	/**
	 * Sets whether the horizontal progress bar in the title should be
	 * indeterminate (the circular is always indeterminate).
	 * <p>
	 * In order for the progress bar to be shown, the feature must be requested
	 * via {@link #requestWindowFeature(int)}.
	 * 
	 * @param indeterminate
	 *            Whether the horizontal progress bar should be indeterminate.
	 */
	public abstract void setProgressBarIndeterminate(boolean indeterminate);

	/**
	 * Sets the progress for the progress bars in the title.
	 * <p>
	 * In order for the progress bar to be shown, the feature must be requested
	 * via {@link #requestWindowFeature(int)}.
	 * 
	 * @param progress
	 *            The progress for the progress bar. Valid ranges are from 0 to
	 *            10000 (both inclusive). If 10000 is given, the progress bar
	 *            will be completely filled and will fade out.
	 */
	public abstract void setProgress(int progress);

	/**
	 * Sets the secondary progress for the progress bar in the title. This
	 * progress is drawn between the primary progress (set via
	 * 
	 * @param secondaryProgress
	 *            The secondary progress for the progress bar. Valid ranges are
	 *            from 0 to 10000 (both inclusive). {@link #setProgress(int)}
	 *            and the background. It can be ideal for media scenarios such
	 *            as showing the buffering progress while the default progress
	 *            shows the play progress.
	 *            <p>
	 *            In order for the progress bar to be shown, the feature must be
	 *            requested via {@link #requestWindowFeature(int)}.
	 */
	public abstract void setSecondaryProgress(int secondaryProgress);

	/**
	 * Get a menu inflater instance which supports the newer menu attributes.
	 * 
	 * @return Menu inflater instance.
	 */
	public MenuInflater getMenuInflater() {
		if (DEBUG)
			Log.d(TAG, "[getMenuInflater]");

		// Make sure that action views can get an appropriate theme.
		if (mMenuInflater == null) {
			if (getActionBar() != null) {
				mMenuInflater = new MenuInflater(getThemedContext(), mActivity);
			} else {
				mMenuInflater = new MenuInflater(mActivity);
			}
		}
		return mMenuInflater;
	}

	/**
	 * Gets the themed context.
	 * 
	 * @return the themed context
	 */
	protected abstract Context getThemedContext();

	/**
	 * Start an action mode.
	 * 
	 * @param callback
	 *            Callback that will manage lifecycle events for this context
	 *            mode.
	 * @return The ContextMode that was started, or null if it was canceled.
	 * @see ActionMode
	 */
	public abstract ActionMode startActionMode(ActionMode.Callback callback);
}
